package data;

import data.dao.ContactsDaoApi;
import pojo.Contacts;
import util.Operation;

import java.io.File;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * 持久层
 * @author mayanwei
 */
public class Persistence implements ContactsDaoApi {

    public static byte[] addressBookBytes = null;
    public static byte[] emailBytes = new byte[20];
    public static byte[] nameBytes = new byte[20];
    public static byte[] phoneNumberBytes = new byte[11];
    public static byte[] resumBytes = null;
    public static byte[] numBytes = new byte[3];

    public static  byte[] getAddressBookBytes(Contacts contact){
        if(contact!=null){

            Operation.rightFillBlank(contact);
            emailBytes = contact.getEmail().getBytes();
            System.out.println(contact.getEmail());
            for (byte b:emailBytes){
                System.out.println(b);
            }
            nameBytes = contact.getName().getBytes();
            System.out.println(contact.getName());
            for (byte b:nameBytes){
                System.out.println(b);
            }
            phoneNumberBytes = contact.getPhoneNumber().getBytes();
            System.out.println(contact.getPhoneNumber());
            for (byte b:phoneNumberBytes){
                System.out.println(b);
            }
            resumBytes = contact.getResume().getBytes();
            System.out.println(contact.getResume());
            for (byte b:resumBytes){
                System.out.println(b);
            }
            //获取变长记录的长度，用三位来表示
            String numStr = Operation.getFormatedStringFromInteger(contact.getResume().length(), 3);


            numBytes = numStr.getBytes();
            addressBookBytes = new byte[numBytes.length+emailBytes.length+nameBytes.length+phoneNumberBytes.length+resumBytes.length];


            System.arraycopy(numBytes,0,
                    addressBookBytes,0, numBytes.length);
            System.arraycopy(emailBytes,0,
                    addressBookBytes,numBytes.length, emailBytes.length);
            System.arraycopy(nameBytes,0,
                    addressBookBytes,numBytes.length+emailBytes.length, nameBytes.length);
            System.arraycopy(phoneNumberBytes,0,
                    addressBookBytes,numBytes.length+emailBytes.length+nameBytes.length, phoneNumberBytes.length);
            System.arraycopy(resumBytes,0,
                    addressBookBytes,numBytes.length+emailBytes.length+nameBytes.length+phoneNumberBytes.length, resumBytes.length);


        }else {
            throw new RuntimeException("contact不能为空！");
        }
        return  addressBookBytes;
    }

    public void save(Contacts contact) {
        /**
         *  记录定长 128+20+20+11+15+3(记录resume的长度) = 207 byte
         */
        byte[] addressBookBytes = Persistence.getAddressBookBytes(contact);

        String finalBinaryContactString = handleContactBytes(addressBookBytes);



//        FileOutputStream fos = null;
//        try {
//            File file = new File("./contact.bat");
//            if(!file.exists()){
//                file.createNewFile();
//            }
//
//            fos = new FileOutputStream(file);
//
//            fos.write(finalContactString.getBytes());
//        } catch (IOException e) {
//            e.printStackTrace();
//        }finally {
//            try {
//                fos.close();
//            } catch (IOException e) {
//                e.printStackTrace();
//            }
//        }
        /**
         * 追加存储到二进制文件中
         */

        if (finalBinaryContactString!=null){
            RandomAccessFile accessFile = null;
            try{
                File file = new File("./contact.bat");
                if(!file.exists()){
                    file.createNewFile();
                }
                accessFile = new RandomAccessFile(file,"rw");
                long origfileLength = accessFile.length();
                accessFile.seek(origfileLength);
                accessFile.write(finalBinaryContactString.getBytes());

            }catch (Exception e){

            }finally {
                try {
                    accessFile.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }
    }

    public String handleContactBytes(byte[] addressBookBytes) {

        /**
         * 获取记录二进制字符串
         */
        String s = Operation.byteArrToBinStr(addressBookBytes);

        /**
         * 获取记录二进制字符串长度，并转化为长度为8为的字符串（不足位，前面补0）
         */
        int slength = s.length();
        String slengthString = Operation.getFormatedStringFromInteger(slength, 8);

        /**
         * 获取格式化的二进制字符串，这里为二进制记录的长度所对应的格式化二进制字符串（长度为 72 位）
         * 例如
         * 00110000 00110000 00110000 00110000 00110000 00110111 01110010 00110101
         */
        String slengthStringBinary = Operation.getFormatedBinaryStringFromBytes(slengthString.getBytes());

        /**
         * 组合二进制记录和二进制记录长度
         */
        StringBuffer contactBinaryBuffer = new StringBuffer();
        contactBinaryBuffer.append(slengthStringBinary);
        contactBinaryBuffer.append(s);

        return contactBinaryBuffer.toString();

    }
    private List<Contacts> find(){
        RandomAccessFile accessFile = null;
        Contacts contact = null;
        List<Contacts> contactsList = new ArrayList<Contacts>();
        try{
            File file = new File("./contact.bat");

            accessFile = new RandomAccessFile(file,"rw");
            long origfileLength = accessFile.length();
            long readedLength = 0L;
            System.out.println(origfileLength);
            byte[] binarySlengthBytes = new byte[72];
            int readflag = accessFile.read(binarySlengthBytes, 0, 72);
            readedLength += binarySlengthBytes.length;
            boolean firstRead = true;
            while (readedLength < origfileLength ){

                if (!firstRead) {
                    readflag = accessFile.read(binarySlengthBytes, 0, 72);
                    readedLength += binarySlengthBytes.length;
                }

                String s1 = Operation.byteArrToBinStr(binarySlengthBytes);
                byte[] slenthBytes = Operation.binStrToByteArr(s1);
                String slengthBinary = new String(slenthBytes).toString();

                System.out.println(slengthBinary);

                byte[] bytes = Operation.binStrToByteArr(slengthBinary);

//                for (byte b:bytes){
//                    System.out.println(b);
//                }

                String slengthStr = new String(bytes);
                System.out.println(slengthStr);
                Integer slength = Integer.valueOf(slengthStr);


                byte [] dataBytes = new byte[slength];
//            accessFile.skipBytes(72);

                readflag = accessFile.read(dataBytes, 0, slength);
                readedLength += slength;

                String binDataStr = new String(dataBytes);

                System.out.println("binDataStr"+binDataStr);


                byte[] emailBytes = new byte[20];
                byte[] nameBytes = new byte[20];
                byte[] phoneNumberBytes = new byte[11];

                byte[] resumLenthBytes = new byte[3];


                byte[] contactBytes = Operation.binStrToByteArr(binDataStr);


                System.arraycopy(contactBytes,0,
                        resumLenthBytes,0,resumLenthBytes.length);
                String s2 = new String(resumLenthBytes);

                Integer resumeLength = Integer.valueOf(s2.trim());
                byte[] resumBytes = new byte[resumeLength];

                System.arraycopy(contactBytes,resumLenthBytes.length,
                        emailBytes,0,emailBytes.length);
                System.arraycopy(contactBytes,resumLenthBytes.length+emailBytes.length,
                        nameBytes,0,nameBytes.length);
                System.arraycopy(contactBytes,resumLenthBytes.length+emailBytes.length+nameBytes.length,
                        phoneNumberBytes,0,phoneNumberBytes.length);
                System.arraycopy(contactBytes,resumLenthBytes.length+emailBytes.length+nameBytes.length+phoneNumberBytes.length,
                        resumBytes,0,resumBytes.length);

                contact  = new Contacts();

                contact.setEmail(new String(emailBytes))
                        .setName(new String(nameBytes))
                        .setPhoneNumber(new String(phoneNumberBytes))
                        .setResume(new String(resumBytes));
                contactsList.add(contact);
                firstRead = false;
            }
            int i= 0;
            for (Contacts c:contactsList ) {
                i++;
                System.out.println("总共"+contactsList.size()+"条记录，第"+i+"条为:"+c.toString());
            }

        }catch (Exception e){
            throw new RuntimeException(e);
        }finally {
            try {
                accessFile.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return contactsList;
    }

    @Override
    public void save(List<Contacts> contactsList) {
        if(contactsList!=null &&contactsList.size()>0 ){
            for (Contacts contact:contactsList){
                this.save(contact);
            }
        }
    }

    @Override
    public List<Contacts> findAll() {
        return this.find();
    }

    @Override
    public Contacts findByEmail(String email) {
        List<Contacts> contactsList = this.find();
        for (Contacts contact:contactsList) {
            String sourceEmail1 = contact.getEmail();
            if(sourceEmail1!=null && sourceEmail1.contains(email)){
                return  contact;
            }
        }
        return null;
    }

    @Override
    public Contacts findByName(String name) {
        List<Contacts> contactsList = this.find();
        for (Contacts contact:contactsList) {
            String sourceName = contact.getName();
            if(sourceName!=null && sourceName.contains(name)){
                return  contact;
            }
        }
        return null;
    }

    @Override
    public Contacts findByPhone(String phone) {
        List<Contacts> contactsList = this.find();
        for (Contacts contact:contactsList) {
            String sourcePhone = contact.getPhoneNumber();
            if(sourcePhone!=null && sourcePhone.contains(phone)){
                return  contact;
            }
        }
        return null;
    }
}
